// class 类型
class Person {
    name: string
    age = 18
}

let p1 = new Person()

console.log(p1.name, p1.age)


// 构造函数
class Person2 {
    name: string
    age: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

let p2 = new Person2('张三', 18)
console.log(p2.name, p2.age)


// 实例方法
class Person3 {
    greet(name: string) {
        console.log(`hi, ${name}`)
    }
}

let p3 = new Person3()
p3.greet('张三')


// extends 继承 (继承父类)
class Person4 {
    move() { console.log('move') }
}

class Person5 extends Person4 {
    break() { console.log('break') }
}
let p5 = new Person5()
p5.move()


// implements 实现 (实现接口)
interface Singale {
    sing(): void
    name: string
}

class Person6 implements Singale {
    name = 'James'
    sing() { console.log('sing') }
}
let p6 = new Person6()
p6.sing()
console.log(p6.name)



// 可见性修饰符 (public, private, protected)
class Person7 {
    public name: string // public 公共属性 默认
    protected sex: string // protected 受保护的属性 只能在类(父类和子类)内部通过this访问 实例对象 不能访问
    private age: number // private 私有属性 只能在当前类(父类)中通过this访问 子类和实例对象不能访问
}


// readonly修饰符 只读属性
// readonly只能修饰属性 不能修饰方法
class Person8 {
    // 如果不给number类型 age类型就是字面量类型 18
    readonly age = 18
    readonly name: string = 'James'
    constructor(name: string) {
        this.name = 'Jack'
    }
    setName(name: string) {
        // 报错 无法给name 赋值 因为name是只读属性
        // this.name = name
    }
}

// 接口也可以使用readonly修饰符
interface Person9 {
    readonly name: string
}
let p9: Person9 = {
    name: 'James'
}
// 报错 无法给name 赋值 因为name是只读属性
// p9.name = 'Jack'


// 类型兼容性
// 除了 函数类型中的参数是 类型少的赋值给类型多的 其他都是类型多的赋值给类型少的
